package com.tencent.qf.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;

/**
 * Copyright (C) 2022 Limited, a Tencent company. All rights reserved.
 * 日期工具类
 *
 * @author p_htaozhou@tencent.com
 * @create: 2022/12/15 19:40
 */

@Slf4j
public class DateUtils {

    public static SimpleDateFormat sdfWhole = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat YMD_HMS_SSS_WHOLE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    public static String YMD_HMS = "yyyy-MM-dd HH:mm:ss";
    public static String YMD_HM = "yyyy-MM-dd HH:mm";
    public static SimpleDateFormat sdfYM = new SimpleDateFormat("yyyyMM");
    public static SimpleDateFormat sdfMD = new SimpleDateFormat("MMdd");
    public static SimpleDateFormat sdfMD_HM = new SimpleDateFormat("MM-dd HH:mm");
    public static SimpleDateFormat SDF_YMD = new SimpleDateFormat("yyyyMMdd");
    public static SimpleDateFormat sdfYMD = new SimpleDateFormat("yyyy-MM-dd");

    public static Date toDate(String date, SimpleDateFormat simpleDateFormat) {
        try {
            return simpleDateFormat.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public static Date toDate(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDateTime date2LocalDateTime(Date date){
        ZoneId zoneId = ZoneId.systemDefault();
        return date.toInstant().atZone(zoneId).toLocalDateTime();
    }

    /**
     * 按照格式 获取LocalDateTime 字符串
     *
     * @param pattern 格式
     * @param time    time
     * @return 字符串
     */
    public static String getLocalDateTimePatternStr(String pattern, LocalDateTime time) {
        if (StringUtils.hasText(pattern)) {
            return DateTimeFormatter.ofPattern(pattern, Locale.GERMANY).format(time);
        } else {
            return DateTimeFormatter.ofPattern(YMD_HMS, Locale.GERMANY).format(time);
        }
    }

    /***
     * @MethodName dayOfYear
     * @Description 计算某一天在当年是第几天
     * @param: year
     * @param: month
     * @param: day
     * @return: int
     * @Author p_htaozhou@tencent.com
     * @Date 2022/12/15 19:41
     */
    public static int dayOfYear(int year, int month, int day) {
        int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (isLeapYear(year)) {
            days[1] = 29;
        }

        for (int i = 0; i < month - 1; i++) {
            day += days[i];
        }
        return day;
    }

    public static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
    }

    /**
     * 获取上月的期间
     */
    public static int getLastPeriod() {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
        date = calendar.getTime();
        return Integer.parseInt(sdfYM.format(date));
    }

    /**
     * 获取当月的期间
     */
    public static int getCurPeriod(boolean end) {
        if (end) {
            return Integer.parseInt(sdfYM.format(new Date()));
        } else {
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR - 1);
            int month = (now.get(Calendar.MONTH) + 1);
            return Integer.parseInt(year + "" + month);
        }
    }

    /**
     * 获取上月的第一天
     */
    public static String getLastMonthFirstDay() {
        Calendar calendar = Calendar.getInstance();//获取当前日期
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);//设置为1号
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return sdfWhole.format(calendar.getTime());
    }

    /**
     * 获取上月的最后一天
     */
    public static String getLastMonthLastDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 0);//设置为1号,当前日期既为本月第一天
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return sdfWhole.format(calendar.getTime());
    }

    /**
     * 几个月后的当天
     *
     * @param sourceDate
     * @param month
     * @return
     */
    public static Date stepMonth(Date sourceDate, int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(sourceDate);
        c.add(Calendar.MONTH, month);
        return c.getTime();
    }

    /**
     * 获取当前的年月日
     */
    public static String getToday() {
        Calendar calendar = Calendar.getInstance();
        return sdfYMD.format(calendar.getTime());
    }

    /**
     * 获取当前的月日 时分
     *
     * @return
     */
    public static String getTodayMDHM() {
        Calendar calendar = Calendar.getInstance();
        return sdfMD_HM.format(calendar.getTime());
    }

    /**
     * 获取当前的年月日
     */
    public static String getSdfWholeToday() {
        Calendar calendar = Calendar.getInstance();
        return sdfWhole.format(calendar.getTime());
    }

    /**
     * 获取当前的月日
     */
    public static String getMonthAndDay() {
        Calendar calendar = Calendar.getInstance();
        return sdfMD.format(calendar.getTime());
    }

    /**
     * 获取当前的年月日
     */
    public static String getYearAndMonthAndDay() {
        Calendar calendar = Calendar.getInstance();
        return SDF_YMD.format(calendar.getTime());
    }

    public static String getCurrentTimeStr() {
        Calendar calendar = Calendar.getInstance();
        return YMD_HMS_SSS_WHOLE.format(calendar.getTime());
    }

    public static String getMonthAndDay(Date date) {
        return sdfMD.format(date.getTime());
    }

    public static String getDayOfDate(Date date) {
        return sdfYMD.format(date.getTime());
    }

    public static String getSdfWholeDayOfDate(Date date) {
        return sdfWhole.format(date.getTime());
    }

    /**
     * String转Date，默认格式 yyyy-MM-dd HH:mm:ss
     *
     * @param date   时间字符串
     * @param format 可以不传 默认为：yyyy-MM-dd HH:mm:ss
     * @return 日期Date对象
     */
    public static Date parseDate(String date, String format) {
        if (StringUtils.hasText(format)) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try {
                return sdf.parse(date);
            } catch (ParseException e) {
                log.error("日期转换异常", e);
                throw new RuntimeException(e);
            }
        }
        try {
            return sdfWhole.parse(date);
        } catch (ParseException e) {
            log.error("日期转换异常", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期根据格式转String
     *
     * @param date   日期
     * @param format 格式
     * @return
     */
    public static String getDayOfDate(Date date, String format) {
        if (StringUtils.hasText(format)) {
            SimpleDateFormat sdfYMD = new SimpleDateFormat(format);
            return sdfYMD.format(date.getTime());
        } else {
            return sdfWhole.format(date.getTime());
        }
    }

    public static String getPreviousDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        return sdfYMD.format(calendar.getTime());
    }


    public static String getPreviousDays(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -day);
        return sdfYMD.format(calendar.getTime());
    }

    public static Date getPreviousDays(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        if (!Objects.isNull(date)) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.DATE, -day);
        return calendar.getTime();
    }

    public static Date getPreviousMinutes(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        if (!Objects.isNull(date)) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.MINUTE, -day);
        return calendar.getTime();
    }

    public static Date getAfterDaysDate(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, day);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getPreviousDaysDate(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DAY_OF_MONTH, -day);
        return calendar.getTime();
    }

    /**
     * 获取当天23：59：59时间点
     *
     * @return
     */
    public static Date getCurrentDayLastSecondTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取当天00：00：00时间点
     *
     * @return
     */
    public static Date getCurrentDayFirstSecondTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    /**
     * 获取前一天23：59：59时间点
     *
     * @return
     */
    public static Date getYesterdayLastSecondTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 1,
                23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取前一天00：00：00时间点
     *
     * @return
     */
    public static Date getYesterdayFirstSecondTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 1,
                0, 0, 0);
        return calendar.getTime();
    }


    /**
     * 获取上一天的年月日
     */
    public static String getYesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        return sdfYMD.format(calendar.getTime());
    }

    /**
     * 获取上个月的今天
     */
    public static String getLastMonthToday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        return sdfYMD.format(calendar.getTime());
    }

    /**
     * 获取某年最后一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static Date getYearLastDate(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    /**
     * 获取某个时间点的前几分钟
     *
     * @param sourceDate 日期
     * @param minutes    多少分钟
     * @return 时间
     */
    public static Date getPreMinutesDate(Date sourceDate, int minutes) {
        Calendar calendar = Calendar.getInstance();
        if (!Objects.isNull(sourceDate)) {
            calendar.setTime(sourceDate);
        }
        calendar.add(Calendar.MINUTE, -minutes);
        return calendar.getTime();
    }

    public static void main(String[] args) {
        Date previousDay = DateUtils.getPreviousDay(DateUtils.getCurrentDayFirstSecondTime(), 7);
        System.out.println(previousDay);
    }

    public static Date getFirstSecondTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    public static Date getLastSecondTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 23);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getPreviousDay(Date date, Integer previous) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -previous);
        return calendar.getTime();
    }

    public static String formatDate(Date date, SimpleDateFormat dateFormat) {
        return dateFormat.format(date);
    }
}
